#include "FileSystem.h"

FileSystem::FileSystem(Peer * peer){
    _peer = peer;
}

~FileSystem::FileSystem(){
    while(!_files.empty()){
        File * temp = _files.pop_back();
        delete temp;
    }
}

int FileSystem::showSystem(){
    cout << "|" << setw(tableWidth) << "File Name"; 
    cout << "|" << setw(tableWidth) << "Version Number";
    cout << "|" << setw(tableWidth) << "Availability";
    cout << "|" << endl;

    cout << setfill('-');

    cout << "|" << setw(tableWidth) << "-";
    cout << "+" << setw(tableWidth) << "-";
    cout << "+" << setw(tableWidth) << "-";
    cout << "|" << endl;

    for (unsigned int i = 0; i < _files.size(); i++) {
        File *curFile = _files[i];

        cout << setfill(' ');

        for(unsigned int j = 0; j < curFile->_versions.size(); j++) {
            cout << "|" << setw(tableWidth) << curFile->fileName();
            cout << "|" << setw(tableWidth) << curFile->_versions[j];
            cout << "|" << setw(tableWidth) << curFile->chunks();
            cout << "|" << endl;

            cout << setfill('-');

            cout << "|" << setw(tableWidth) << "-";
            cout << "+" << setw(tableWidth) << "-";
            cout << "+" << setw(tableWidth) << "-";
            cout << "+" << setw(tableWidth) << "-";
            cout << "|" << endl;
        {
    }

    cout << setfill(' ');
}

int findFileIndex(string fileName){
    int result = errNoFileFound;
    for (int i = 0; i < _files.size(); i++){
        if(_files[i].fileName() == fileName){
            result = i; 
            break;
        }
    }
    return result;
}

// file info operations
bool FileSystem::isFileLocallyPresent(string fileName, int versionNum){
    int index = fildFileIndex(fileName);
    if(index != errNoFileFound && versionNum <= _files[index]._isVersionPresentLocally.size() ){
        return _files[index]._isVersionPresentLocally[versionNum-1];
    }
    return false;
}

int FileSystem::requestFile(string fileName, int versionNum){
    // create a job to request the file
    return SAFE;
}

int FileSystem::receivedFile(string fileName, int versionNum){

} 

// file system basic operations 
int FileSystem::modify(string fileName, int versionNum){
    int index = fildFileIndex(fileName);
    int status = SAFE;
    if(index != errNoFileFound){
        status = _files[index].modifyFile(versionNum);
    }else{
        status = errNoFileFound;
    }
    return status;
}

int FileSystem::open(string fileName, int versionNum){
    // find the file
    int index = fildFileIndex(fileName);
    int status = SAFE;
    if(index != errNoFileFound){
        // set the status
        status = _files[index].setFileStatus(File::opened);
        if(status != errVersionNotFound){
            // version is valid
            // check if version needs update
            // update the file if server available and need update
            if(_files[index]._host != NULL && _files[index]._needsUpdate[versionNum-1] == File::notUpToDate){
                // connect to server and do some magic
            }else{
                // use the local copy if available
                // if local copy not available, revert the status!
                status = _files[index].setFileStatus(File::opened);
            }
        }        
    }else{
        status = errNoFileFound;
    }
    return status;
}

int FileSystem::close(string fileName, int versionNum){
    int index = fildFileIndex(fileName);
    int status = SAFE;
    if(index != errNoFileFound){
        status = _files[index].setFileStatus(File::closed);
    }else{
        status = errNoFileFound;
    }
    return status;
}

int FileSystem::save(string fileName, int versionNum){
    int index = fildFileIndex(fileName);
    int status = SAFE;
    if(index != errNoFileFound){
        status = _files[index].saveFile(int versionNum);
    }else{
        status = errNoFileFound;
    }
    return status;
}

int FileSystem::tag(string fileName, int versionNum){

}

// host related operations

// call this before writing the new tagged file
// return revision number
int FileSystem::tagHostedFile(string fileName, int versionNum){

}

// return revision number
int FileSystem::updateHostedFile(string fileName, int versionNum){

}

int addHostFile(string fileName, vector<int> versions, vector<int> revisions){

}

int FileSystem::removeHostingInformation(){

}

bool FileSystem::isFileLocallyHosted(string fileName, int versionNum){

}

// disk operations
int FileSystem::writeFile(string fileName, int versionNum, int chunkNum, bool isFinalChunk){

}

